/*
 *	Copyright (C) 2008 CRIMERE
 *	Copyright (C) 2008 Jean-Marc Mercier
 *	
 *	This file is part of OTS (optimally transported schemes), an open-source library
 *	dedicated to scientific computing. http://code.google.com/p/optimally-transported-schemes/
 *
 *	CRIMERE makes no representations about the suitability of this
 *	software for any purpose. It is provided "as is" without express or
 *	implied warranty.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */


/*! \file BackwardDifference.h
    \brief Multidimensional generalization of finite difference backward operators.

	Multidimensional generalization of the classical backward difference operator
	\f[
			\delta_{\bar{x}} u_i=\frac{u_i-u_{i-1}}{h}
	\f]
	The geometry is the unit cube \f$[0,1]^N\f$, where N is given by data::Dim
*/

#if !defined(_BackwardDifference_)
#define _BackwardDifference_
#include <src/math/BoundaryCondition/classicalgraphdefinition.h>
#include <src/math/Operators/FiniteDifferenceOperators.h>
#include <src/algorithm/Evolution_Algorithm/CFL_traits.h>
#include <src/algorithm/Evolution_Algorithm/Predictor_traits.h>


/*! 
    \brief Common multidimensional behavior for all finite difference backward operators.

	Common multidimensional behavior for all finite difference backward operators, i.e.
	\f[
			\delta_{\bar{x}} u_i=\frac{u_i-u_{i-1}}{h}
	\f]
 
	This class is non compilable : it is used to check at compile time whether the backward difference operator has been implemented
	for a given set of data and Boundary_type conditions.
*/
template <class data, std::size_t = data::Dim, class V = smart_ptr<data> >
class D__x 
	: public FiniteDifferenceOperator<data,data,V>
 {
//! return " D__x u" \f$.
		static std::string get_name(){return " D__x u";};
		OS_STATIC_CHECK(false); // to implement
};

/*! 
    \brief One dimensional specialization of difference backward operators.

	\f[
			\delta_{\bar{x}} u_i=\frac{u_i-u_{i-1}}{h}
	\f]
 */
template <class data,class V>
class D__x<data,1,V>  
	: public FiniteDifferenceOperator<data,data,V>
{
public :
		enum:std::size_t												{Order = 1};
		typedef Backward												Centered_Type;
		typedef typename data::Boundary_type							Boundary_type;
		
		typedef FiniteDifferenceOperator								Base;
		typedef  typename Base::Base_Cast								Base_Cast;
		typedef D__x													type;

//! return " D__x u" \f$.
		static std::string get_name(){return " D__x u";};
		D__x( ) : operator_interface_(*this,make_2<base_value_type>(0.,1.)) {};
		D__x(const D__x & data) : operator_interface_(*this,make_2<base_value_type>(0.,1.)),  Base(data) {};
		D__x(const weight_set_type & data) :  operator_interface_(*this,make_2<base_value_type>(0.,1.)), Base(data) {};

		D__x(const Base_Cast &first) : operator_interface_(*this), Base(first)
		{};
		virtual ~D__x(){};
		D__x & operator = (const D__x & from) {
			Base::operator =(from);
			return *this;
		};
		virtual void update() {
			operator_interface_.update();
		};
		//! Optimized code for backward difference operator.
		virtual result_type operator()(typename argument_type from) const
		{
			return (from - (from>>1) )*from.size();
		};
		//! Factory method.
		virtual smart_ptr_type Create_Instance() const {
			return Create_Instance_helper_arg<type,weight_set_type>(&weight_set_);
		};
private :
		operator_interface<D__x,Order,Centered_Type,Boundary_type> operator_interface_;
};


/*! \brief Bind operator of backward difference operator D__x_traits

	This is the time Bind operator of backward difference operator D__x_traits, that is D__x_t(t,u)=D__x(u)
*/
template <class data, typename Time = OS_double >
struct D__x_t : public BindTimeOperator<D__x<data> ,Time > {

	typedef D__x_t															time_operator_type;
	typedef BindTimeOperator<time_operator_type ,Time >						Base;
	D__x_t(){};
};


#endif